
package com.xiguthings.xiniu.iot.device.state.jedis;

import java.util.HashMap;
import java.util.Map;

import javax.swing.Spring;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.xiguthings.xiniu.iot.common.DeviceData;
import com.xiguthings.xiniu.iot.device.state.common.SpringUtils;
import com.xiguthings.xiniu.iot.device.state.controller.DataCenter;

@Component
public class DeviceDataBuffer {

	private final Logger LOGGER = LoggerFactory.getLogger(DeviceDataBuffer.class);

	// 缓冲区最大的数量
	@Value("${redis.pipeline.buffer.maxSize}")
	private int maxSize;
	// 缓冲区最大缓存时间
	@Value("${redis.pipeline.buffer.maxCacheTime}")
	private long maxCacheTime;

	@Autowired
	private JedisClient jedisClient;
	// 记录上一次flush的时间
	private long lastFlushTs;

	/**
	 * 报错设备状态的map
	 */
	private Map<String, DeviceData> deviceStates = new HashMap<>();

	/**
	 * 
	 * @param maxSize
	 * @param maxCacheTime
	 */
	public DeviceDataBuffer(int maxSize, long maxCacheTime) {
		this.maxSize = maxSize;
		this.maxCacheTime = maxCacheTime;
		// jedisClient = SpringUtils.getBean(JedisClient.class);
	}

	public DeviceDataBuffer() {
		init();
	}

	private void init() {
		if (maxSize == 0) {
			maxSize = 1000;
		}
		if (maxCacheTime == 0) {
			maxCacheTime = 1000;
		}

		// 时间控制缓冲区的线程
		Thread t = new Thread(new Runnable() {
			@Override
			public void run() {
				while (true) {
					// 如果达成时间条件，则flush
					if (System.currentTimeMillis() - lastFlushTs > maxCacheTime) {
						flush();
					}
					try {
						Thread.sleep(maxCacheTime);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});
		t.start();
	}

	public synchronized void flush() {
		if (System.currentTimeMillis() - lastFlushTs < 1000) {
			// 如果距离上一次flush小于1秒 则不会进行flush
			return;
		}
		int size = bufferSize();
		if (size < 1) {
			return;
		}
		if (jedisClient == null) {
			jedisClient = SpringUtils.getBean(JedisClient.class);
		}
		jedisClient.pipelineHSets(deviceStates);
		LOGGER.info("批量写入redis，条数deviceData：{}", size);
		deviceStates.clear();
		lastFlushTs = System.currentTimeMillis();
	}

	/**
	 * 向缓冲区加入数据
	 *
	 * @param deviceData
	 */
	public void add(DeviceData deviceData) {
		String hkey = DataCenter.getDeviceStatusRedisKey(deviceData);
		deviceStates.put(hkey, deviceData);
		// 如果达成条件数量，则flush
		if (bufferSize() >= maxSize) {
			flush();
		}
	}

	private synchronized int bufferSize() {
		return deviceStates.size();
	}

	/**
	 * 查看buffer中是否有该设备的老数据
	 * 
	 * @param deviceData
	 * @return
	 */
	public DeviceData getOldDeviceData(DeviceData deviceData) {
		String hkey = deviceData.getHead().getProductId() + "/" + deviceData.getHead().getDeviceId();
		return deviceStates.get(hkey);
	}

}
